/* 
给定一个包含多个Promise的数组和一个并发限制limit。
要求实现一个函数，使得先并行执行limit个Promise，
每当有Promise完成时，就立即执行下一个，直到所有Promise都执行完毕。

比如，当数组长度为10，limit=2时，
应该先同时执行前两个，每当其中一个完成，就接着执行第三个，
以此类推，直到所有10个都完成。
*/

async function runPromisesWithLimit(promiseFunctions, limit) {
  const results = []; // 存储每个Promise的结果（按顺序）
  const executing = new Set(); // 记录正在执行的Promise
  let index = 0; // 当前要处理的Promise索引

  // 循环处理所有Promise
  while (index < promiseFunctions.length) {
    // 当前执行的Promise数量未达上限时，启动新Promise
    if (executing.size < limit) {
      const currentIndex = index++; // 记录当前Promise的索引，然后将索引 +1
      const promise = promiseFunctions[currentIndex]() // 执行Promise函数
        .then(result => {
          results[currentIndex] = result; // 存储结果（保持顺序）
        })
        .catch(error => {
          results[currentIndex] = error; // 存储错误
        })
        .finally(() => {
          executing.delete(promise); // 无论成功/失败，执行完移除
        });
      executing.add(promise); // 将新Promise加入执行队列
    } else {
      // 队列已满，等待任意一个Promise完成
      // 使用 await 关键字会暂停当前 async 函数（runPromisesWithLimit）的执行，
      // 直到 executing 集合中的某个 Promise 率先完成。
      // 一旦有一个 Promise 完成，await 表达式就会返回该 Promise 的结果，
      // 并且 async 函数会继续执行后续代码。
      await Promise.race(executing);
    }
  }
  // 等待所有剩余Promise执行完毕
  // 使用 await 关键字会暂停 async 函数的执行，直到 executing 集合中的所有 Promise 都完成。
  // 当所有 Promise 都完成后，await 表达式会返回一个包含所有结果的数组，
  // 并且 async 函数会继续执行后续代码，最终返回存储所有结果的 results 数组
  await Promise.all(executing);
  return results;
}

// 示例测试
const promiseFunctions = [
  () => delayResolve(1000, 1),
  () => delayResolve(500, 2),
  () => delayResolve(800, 3),
  () => delayResolve(200, 4),
  () => delayResolve(300, 5),
];

// 工具函数：模拟延迟成功的Promise
function delayResolve(ms, value) {
  return new Promise(resolve =>
    setTimeout(() => {
      console.log(`${value} done`);
      resolve(value);
    }, ms)
  );
}

// 执行测试（limit=2）
runPromisesWithLimit(promiseFunctions, 2)
  .then(results => console.log("Results:", results));